package core

import (
	"errors"
	"sync"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

var (
	jwtSecret = []byte("lan-file-transfer-secret-key-2024")
)

// JWTClaims JWT声明
type JWTClaims struct {
	ClientIP string `json:"client_ip"`
	jwt.RegisteredClaims
}

// GenerateToken 生成JWT Token
func GenerateToken(clientIP string) (string, error) {
	claims := JWTClaims{
		ClientIP: clientIP,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(2 * time.Hour)),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtSecret)
}

// ValidateToken 验证Token
func ValidateToken(tokenString string) (*JWTClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
		return claims, nil
	}

	return nil, errors.New("无效的Token")
}

// FailedAttempt 失败尝试记录
type FailedAttempt struct {
	Count     int
	LockUntil time.Time
}

// SecurityManager 安全管理器
type SecurityManager struct {
	failedAttempts sync.Map // key: IP, value: *FailedAttempt
	passwordHash   string
	mu             sync.RWMutex
}

// NewSecurityManager 创建安全管理器
func NewSecurityManager(password string) *SecurityManager {
	return &SecurityManager{
		passwordHash: HashPassword(password),
	}
}

// SetPassword 设置密码
func (sm *SecurityManager) SetPassword(password string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	sm.passwordHash = HashPassword(password)
}

// VerifyPassword 验证密码
func (sm *SecurityManager) VerifyPassword(password string) bool {
	sm.mu.RLock()
	defer sm.mu.RUnlock()
	return sm.passwordHash == HashPassword(password)
}

// CheckIPLocked 检查IP是否被锁定
func (sm *SecurityManager) CheckIPLocked(ip string) (bool, time.Duration) {
	value, exists := sm.failedAttempts.Load(ip)
	if !exists {
		return false, 0
	}

	attempt := value.(*FailedAttempt)
	if time.Now().Before(attempt.LockUntil) {
		remaining := time.Until(attempt.LockUntil)
		return true, remaining
	}

	// 锁定期已过,清除记录
	sm.failedAttempts.Delete(ip)
	return false, 0
}

// RecordFailedAttempt 记录失败尝试
func (sm *SecurityManager) RecordFailedAttempt(ip string) {
	value, exists := sm.failedAttempts.Load(ip)

	if !exists {
		sm.failedAttempts.Store(ip, &FailedAttempt{
			Count:     1,
			LockUntil: time.Time{},
		})
		return
	}

	attempt := value.(*FailedAttempt)
	attempt.Count++

	// 3次失败锁定5分钟
	if attempt.Count >= 3 {
		attempt.LockUntil = time.Now().Add(5 * time.Minute)
	}

	sm.failedAttempts.Store(ip, attempt)
}

// ClearFailedAttempt 清除失败记录(验证成功时)
func (sm *SecurityManager) ClearFailedAttempt(ip string) {
	sm.failedAttempts.Delete(ip)
}

// CleanupExpired 清理过期记录(定时任务)
func (sm *SecurityManager) CleanupExpired() {
	sm.failedAttempts.Range(func(key, value interface{}) bool {
		attempt := value.(*FailedAttempt)
		if !attempt.LockUntil.IsZero() && time.Now().After(attempt.LockUntil) {
			sm.failedAttempts.Delete(key)
		}
		return true
	})
}

// Semaphore 信号量(用于并发控制)
type Semaphore struct {
	ch chan struct{}
}

// NewSemaphore 创建信号量
func NewSemaphore(max int) *Semaphore {
	return &Semaphore{
		ch: make(chan struct{}, max),
	}
}

// Acquire 获取信号量
func (s *Semaphore) Acquire() {
	s.ch <- struct{}{}
}

// Release 释放信号量
func (s *Semaphore) Release() {
	<-s.ch
}

// TryAcquire 尝试获取信号量(非阻塞)
func (s *Semaphore) TryAcquire() bool {
	select {
	case s.ch <- struct{}{}:
		return true
	default:
		return false
	}
}
